#
# BioMart module for BioMart::Formatter::SORT_HTML
#
# You may distribute this module under the same terms as perl
# itself.

# POD documentation - main docs before the code.

=head1 NAME

BioMart::Formatter::TSV

=head1 SYNOPSIS



=head1 DESCRIPTION

When given a BioMart::ResultTable containing the results of 
a BioMart::Query the TSV Formatter will return tabular output
with one line for each row of data in the ResultTable and tabs
separating the individual entries in each row. The getDisplayNames
and getFooterText can be used to return appropiately formatted
headers and footers respectively

=head1 AUTHORS

=over

=item *
Syed Haider
=back

=head1 CONTACT

This module is part of the BioMart project
http://www.biomart.org

Questions can be posted to the mart-dev mailing list:
mart-dev@ebi.ac.uk

=head1 METHODS

=cut

package BioMart::Formatter::SORT_HTML;

use strict;
use warnings;

# Extends BioMart::FormatterI
use base qw(BioMart::FormatterI);
use Readonly;

# Constants
Readonly my $FIELD_DELIMITER  => qq{\t};
Readonly my $RECORD_DELIMITER => qq{\n};

# HTML templates
my $current_rowcount = 0; # keep track of number of rows printed out
Readonly my $FOOTER_TMPL => qq{</div>

</body>
</html>
};
Readonly my $HEADER_TMPL => q{<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
  <title>%s</title>
  <link rel="stylesheet" type="text/css" href="/martview/martview.css" />
</head>
<body>

<table>
};
Readonly my $ROW_START_TMPL1 => qq{<tr>\n};
Readonly my $ROW_START_TMPL2 => qq{<tr>\n};
Readonly my $HEADERFIELD_TMPL1     => qq{  <th>%s</th>\n};
Readonly my $HEADERFIELD_TMPL2    => qq{  <th>%s</th>\n};
Readonly my $NORMALFIELD_TMPL1     => qq{  <td>%s</td>\n};
Readonly my $ROW_END_TMPL   => qq{</tr>\n};

sub _new {
    my ($self) = @_;

    $self->SUPER::_new();

	$self->attr('all_rows', undef);
	$self->attr('processed_results', undef);
}

sub processQuery {
    my ($self, $query) = @_;

    $self->set('original_attributes',[@{$query->getAllAttributes()}]) 
	if ($query->getAllAttributes());
    $query = $self->setHTMLAttributes($query);
    $self->set('query',$query);
    return $query;
}

sub nextRow {
    my $self = shift;

    my $rtable = $self->get('result_table');
    my $all_rows = $self->get('all_rows');
    my $processed_results = $self->get('processed_results');

    
    my $row = $rtable->nextRow;
    if (!$row){
    	if ($all_rows) {
    		# SORT on the col number
    		my $sort_index = $self->getColumnIndexForSort();
    		foreach my $res_row (@$all_rows) {
				($sort_index == -1) ? ( push @{$processed_results->{1}}, $res_row )
    								: ( push @{$processed_results->{$res_row->[$sort_index]}}, $res_row );
    		}
    		
    		$self->set('all_rows', undef);
    		$self->set('processed_results', $processed_results);
    		return "\n";
    	}
    	# lets start sending the processed results one by one, in order to keep track of number of rows returned
    	elsif ($processed_results) {
			# my $ret_row = shift @$processed_results;
    		my $ret_row;
    		
    		BREAK: foreach my $prot_score (sort {$b <=> $a} keys %$processed_results) {
    			$ret_row = shift @{$processed_results->{$prot_score}};
    			if ($ret_row) {
	    			last BREAK;
    			}
    		}
    		
    		$self->set('processed_results', $processed_results);
    		
    		
			if (!$ret_row){
				return;
			}
    		
    		my $new_row;
    		map { $_ = q{} unless defined ($_); } @$ret_row;
			my $attribute_positions = $self->get('attribute_positions');
   			my $attribute_url_positions = $self->get('attribute_url_positions');
			my $attribute_url = $self->get('attribute_url');

			for (my $i = 0; $i < @{$attribute_positions}; $i++){
				# superscripting for emma mart
				# $$ret_row[$$attribute_positions[$i]] =~ s/\<(.*)\>/<span style="vertical-align:super;font-size:0.8em">$1<\/span>/;

				if ($$attribute_url[$i]){
					print STDERR "\n\n";
					my @url_data = map {$$ret_row[$_]} @{$$attribute_url_positions[$i]};
					my $url_string = sprintf($$attribute_url[$i],@url_data);
					push @{$new_row}, '<a href="'.$url_string.'" target="_blank">'.
						$$ret_row[$$attribute_positions[$i]]."</a>";
				}
				else{
					push @{$new_row},$$ret_row[$$attribute_positions[$i]];
				}
			}

			$current_rowcount++;
			my $fields_string = '';
			map{ $fields_string .= sprintf ($NORMALFIELD_TMPL1, defined ($_) ? $_ : ''); } @{$new_row};
			return ($current_rowcount % 2 == 0 ? $ROW_START_TMPL1 : $ROW_START_TMPL2)
	                              . $fields_string
                                      . $ROW_END_TMPL;
    		
    		#return $ret_row;
    	}
        else {
        	return;
        }
    }
    # Escape delimiters in value-strings
    foreach(@{$row}) {
		$_ = q{} unless defined ($_);
		$_ =~ s/$FIELD_DELIMITER/\$FIELD_DELIMITER/g;
    }
    
    push @$all_rows, $row;
    $self->set('all_rows', $all_rows);
    
    return "\n";
}

sub getDisplayNames {
    my $self = shift;

    my $original_attributes = $self->get('original_attributes');
    my $dataset1_end = $self->get('dataset1_end');
    my $query = $self->get('query');
    my $registry = $query->getRegistry;
    my $final_dataset_order = $query->finalDatasetOrder;
    
    my @attribute_display_names;
    my @original_dataset_attributes;
    foreach my $dataset(@$final_dataset_order){
	foreach (@{$original_attributes}){
	    push @original_dataset_attributes,$_ 
		if ($_->dataSetName eq $dataset);
	}
    }
    foreach my $original_attribute(@original_dataset_attributes){
	push @attribute_display_names, $original_attribute->displayName;
    }

    # print the display names    
    my $header_string = sprintf $HEADER_TMPL, '';
    $header_string .= $ROW_START_TMPL1;
#    map{ $header_string .= 
#	     sprintf $HEADERFIELD_TMPL, $_ } @attribute_display_names;
    map{ $header_string .= sprintf $HEADERFIELD_TMPL1, $_ } @attribute_display_names[0..$dataset1_end];
    map{ $header_string .= sprintf $HEADERFIELD_TMPL2, $_ } @attribute_display_names[$dataset1_end+1..@attribute_display_names-1];
    $header_string .= $ROW_END_TMPL;
    return $header_string;
}

# Override empty-string returning method in superclass, to return proper 
# table- and document-closing tags (to keep HTML valid).
sub getFooterText {   
    return q{
</table>
</body>
</html>
};
}

sub getMimeType {
    return 'text/html';
}

sub getColumnIndexForSort {
    my $self = shift;
    my @displayNames = $self->getTextDisplayNames();
    my $index = 0;
    foreach my $col (@displayNames) {
    	if ($col eq "Protein score") {
    		return $index;
    	}
    	$index++;
    }
    
    # protein score doesnt exist in output columns, so no sorting will be done
    return -1;
}



1;



